
package com.code.ape.codeape.device.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.code.ape.codeape.admin.api.entity.SysUser;
import com.code.ape.codeape.admin.api.feign.RemoteUserService;
import com.code.ape.codeape.common.core.constant.CacheConstants;
import com.code.ape.codeape.common.core.util.AssertUtil;
import com.code.ape.codeape.common.core.util.R;
import com.code.ape.codeape.common.core.util.RetOps;
import com.code.ape.codeape.common.security.service.CodeapeUser;
import com.code.ape.codeape.common.security.util.SecurityUtils;
import com.code.ape.codeape.device.api.dto.DeviceInfoDTO;
import com.code.ape.codeape.device.api.entity.DeviceInfo;
import com.code.ape.codeape.device.api.entity.DeviceRelation;
import com.code.ape.codeape.device.api.util.DeviceCheckUtil;
import com.code.ape.codeape.device.api.vo.DeviceInfoVO;
import com.code.ape.codeape.device.mapper.DeviceInfoMapper;
import com.code.ape.codeape.device.mapper.DeviceRelationMapper;
import com.code.ape.codeape.device.service.DeviceInfoService;
import com.code.ape.codeape.device.service.DeviceRelationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 设备信息表
 *
 * @author 公众号：码猿技术专栏   版权：不才陈某所署，侵权必究
 * @date 2023-05-25 16:20:29
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceInfo> implements DeviceInfoService {


	private final DeviceRelationMapper deviceRelationMapper;

	private final DeviceRelationService deviceRelationService;

	private final RemoteUserService remoteUserService;

    @Override
	@Transactional
	@CacheEvict(value = CacheConstants.DEVICE_DEVICE_SN,key = "T(com.code.ape.codeape.common.security.util.SecurityUtils).getUser().hosId")
    public Boolean addDevice(DeviceInfoDTO dto) {
        //step1 设备号校验，唯一
		Assert.isTrue(DeviceCheckUtil.checkSn(dto.getSn()),"SN号不符合规则！");
		Long total = baseMapper.selectCount(Wrappers.<DeviceInfo>lambdaQuery()
				.eq(DeviceInfo::getSn, dto.getSn()));
		Assert.isTrue(total==0,"SN号重复添加！");

		//step2 入库
		DeviceInfo deviceInfo = new DeviceInfo();
		BeanUtil.copyProperties(dto,deviceInfo);
		CodeapeUser codeapeUser = Objects.requireNonNull(SecurityUtils.getUser());
		deviceInfo.setHosId(codeapeUser.getHosId());
		deviceInfo.setEnterId(codeapeUser.getId());
		deviceInfo.setEnterTime(LocalDateTime.now());
		deviceInfo.setProductName("码猿设备");
		deviceInfo.setDevAuthId(dto.getDevAuthId());
		int i = baseMapper.insert(deviceInfo);
		Assert.isTrue(i==1,"设备添加失败");

		//step3 科室关联关系入库
		List<DeviceRelation> deviceRelations = dto.getDeptAuths().stream().map(data -> DeviceRelation.builder()
				.deptId(data)
				.deviceId(deviceInfo.getId())
				.build()).collect(Collectors.toList());
		boolean b = deviceRelationService.saveBatch(deviceRelations);
		Assert.isTrue(b,"设备添加失败");
		return Boolean.TRUE;
    }

	@Override
	public Page<DeviceInfoVO> listPage(Page<DeviceInfoVO> page, DeviceInfoDTO dto) {
		//step1 执行分页查询
    	Page<DeviceInfoVO> pageVo = baseMapper.selectDevicePage(page, dto);

    	//step2 获取入库人姓名
		List<DeviceInfoVO> records = pageVo.getRecords();
		//入库人的全部的id
		Set<Long> enterIds = records.stream().filter(Objects::nonNull).map(DeviceInfoVO::getEnterId).collect(Collectors.toSet());

		//step3 调用admin服务获取，入库人姓名不是展示必须，即使服务调用失败也不抛出异常，try起来
		if (CollectionUtil.isNotEmpty(enterIds)) {
			List<SysUser> enterList=new ArrayList<>();
			try{
				R<List<SysUser>> resultEnterUser = remoteUserService.listUserInfoByIds(enterIds);
				enterList=RetOps.of(resultEnterUser).getData().orElse(new ArrayList<>());
			}catch (Exception ex){
				log.error("调用用户服务异常，参数：{}，异常信息：{}", JSON.toJSON(enterIds),ex.getLocalizedMessage());
			}

			if (CollectionUtil.isNotEmpty(enterList)){
				Map<Long, SysUser> userMap = enterList.stream().collect(Collectors.groupingBy(SysUser::getUserId, Collectors.collectingAndThen(Collectors.toList(), list -> list.get(0))));
				records.stream().peek(entity-> entity.setEnterName(Optional.ofNullable(userMap.get(entity.getEnterId())).orElse(new SysUser()).getName())).collect(Collectors.toList());
			}
		}
		return pageVo;
	}

	@Transactional
	@Override
	@CacheEvict(value = CacheConstants.DEVICE_DEVICE_SN,
			key = "T(com.code.ape.codeape.common.security.util.SecurityUtils).getUser().hosId")
	public Boolean updateDevice(DeviceInfoDTO dto) {
    	//step1 查询
		DeviceInfo deviceInfo = baseMapper.selectById(dto.getId());
		Assert.isTrue(Objects.nonNull(deviceInfo),"设备不存在");
		//step2 如果SN好变了，重新校验
		if (!StrUtil.equals(deviceInfo.getSn(),dto.getSn())){
			boolean check = DeviceCheckUtil.checkSn(dto.getSn());
			Assert.isTrue(check,"SN号不符合规则！");
			Long total = baseMapper.selectCount(Wrappers.<DeviceInfo>lambdaQuery()
					.eq(DeviceInfo::getSn, dto.getSn()));
			Assert.isTrue(total==0,"SN号重复添加！");
		}
		DeviceInfo info = new DeviceInfo();
		BeanUtil.copyProperties(dto,info);
		//step3 更新
		int deviceRows = baseMapper.updateById(info);
		Assert.isTrue(deviceRows==1,"更新失败！");
		if (CollectionUtil.isNotEmpty(dto.getDeptAuths())){
			//step4 删除权限重新入库
			deviceRelationMapper.delete(Wrappers.<DeviceRelation>lambdaQuery().eq(DeviceRelation::getDeviceId,dto.getId()));
			List<DeviceRelation> deviceRelations = dto.getDeptAuths().stream().map(deptId -> DeviceRelation.builder()
					.deviceId(dto.getId())
					.deptId(deptId)
					.build()).collect(Collectors.toList());
			deviceRelationService.saveBatch(deviceRelations);
		}
		return Boolean.TRUE;
	}

	@Transactional
	@CacheEvict(value = CacheConstants.DEVICE_DEVICE_SN,
			key = "T(com.code.ape.codeape.common.security.util.SecurityUtils).getUser().hosId")
	@Override
	public Boolean removeDeviceById(Long id) {
		//todo 这里只是逻辑删除调改台设备，相关权限暂时不删除
		int deviceRows = baseMapper.deleteById(id);
		Assert.isTrue(deviceRows==1,"删除失败！");
		return Boolean.TRUE;
	}

    @Override
    public DeviceInfoVO getDeviceInfoBySn(String sn) {
    	//step1 查询设备
		DeviceInfo deviceInfo = baseMapper.selectOne(Wrappers.<DeviceInfo>lambdaQuery().eq(DeviceInfo::getSn, sn));
		AssertUtil.isTrue(Objects.nonNull(sn),"设备不存在");
		//step2 获取设备的关联科室权限
		List<DeviceRelation> deviceRelations = deviceRelationService.list(Wrappers.<DeviceRelation>lambdaQuery().eq(DeviceRelation::getDeviceId, deviceInfo.getId()));

		//step3 封装VO
		DeviceInfoVO infoVO = BeanUtil.toBean(deviceInfo, DeviceInfoVO.class);
		List<Long> deptAuths=new ArrayList<>();
		deptAuths.add(deviceInfo.getDeptId());
		if (CollectionUtil.isNotEmpty(deviceRelations)){
			//设备的权限：设备绑定的科室+设备的关联的科室
			deptAuths = deviceRelations.stream().map(DeviceRelation::getDeptId).collect(Collectors.toList());
		}
		infoVO.setDeptAuths(deptAuths);
		return infoVO;
	}
}
